import 'dart:async';

typedef ModifyFunc = FutureOr<String?> Function(String source, Map yamlMap);

class FunctionBean {
  final String path;
  final ModifyFunc func;
  FunctionBean({required this.path, required this.func});
}

FunctionBean changeAndroidAppName() {
  // ensure app_name in pubspec.yaml
  return FunctionBean(
    path: 'android/app/src/main/AndroidManifest.xml',
    func: (String source, Map yamlMap) {
      if (yamlMap.containsKey('app_name')) {
        String appName = "${yamlMap['app_name']}";
        final labelMatch = RegExp(
          r'android:label="([^"]*)"',
        ).firstMatch(source);
        if (labelMatch != null && labelMatch.group(1) == appName) {
          return null;
        }
        var newXmlContent = source.replaceFirst(
          RegExp(r'android:label="[^"]*"'),
          'android:label="$appName"',
        );
        return newXmlContent;
      } else {
        print('ensure app_name in pubspec.yaml');
        return null;
      }
    },
  );
}

FunctionBean changeIosAppName() {
  // ensure app_name in pubspec.yaml
  return FunctionBean(
    path: 'ios/Runner/Info.plist',
    func: (String source, Map yamlMap) {
      if (yamlMap.containsKey('app_name')) {
        String appName = "${yamlMap['app_name']}";
        final match = RegExp(
          r'<key>CFBundleDisplayName</key>\s*<string>([^<]*)</string>',
        ).firstMatch(source);
        if (match != null && match.group(1) == appName) {
          return null;
        }
        String content = source.replaceFirst(
          RegExp(r'<key>CFBundleDisplayName</key>\s*<string>[^<]*</string>'),
          '<key>CFBundleDisplayName</key>\n\t<string>$appName</string>',
        );
        return content;
      } else {
        print('ensure app_name in pubspec.yaml');
        return null;
      }
    },
  );
}

FunctionBean changeAndroidPackageName() {
  // ensure package_name in pubspec.yaml
  return FunctionBean(
    path: 'android/app/build.gradle.kts',
    func: (String source, Map yamlMap) {
      if (yamlMap.containsKey("package_name")) {
        String packageName = "${yamlMap['package_name']}";
        final appIdRegex = RegExp(r'applicationId\s*=\s*"(.*?)"');
        final appIdMatch = appIdRegex.firstMatch(source);
        if (appIdMatch != null && appIdMatch.group(1) != packageName) {
          String content = source.replaceFirst(
            appIdRegex,
            'applicationId = "$packageName"',
          );
          return content;
        } else {
          return null;
        }
      } else {
        print('ensure package_name in pubspec.yaml');
        return null;
      }
    },
  );
}

FunctionBean changeAndroidSignType() {
  // ensure android_sign in pubspec.yaml
  return FunctionBean(
    path: 'android/app/build.gradle.kts',
    func: (String source, Map yamlMap) {
      if (yamlMap.containsKey('android_sign')) {
        String signingName = "${yamlMap['android_sign']}";
        final signingRegex = RegExp(
          r'signingConfig\s*=\s*signingConfigs\.getByName\("(.*?)"\)',
        );
        final signingMatch = signingRegex.firstMatch(source);
        if (signingMatch != null && signingMatch.group(1) != signingName) {
          String content = source.replaceFirst(
            signingRegex,
            'signingConfig = signingConfigs.getByName("$signingName")',
          );
          return content;
        } else {
          return null;
        }
      } else {
        print('ensure android_sign in pubspec.yaml');
        return null;
      }
    },
  );
}

FunctionBean changeIosPackageName() {
  // ensure package_name in pubspec.yaml
  return FunctionBean(
    path: 'ios/Runner.xcodeproj/project.pbxproj',
    func: (String source, Map yamlMap) {
      if (yamlMap.containsKey('package_name')) {
        String packageName = "${yamlMap['package_name']}";
        var newContent = source.replaceAllMapped(
          RegExp(r'PRODUCT_BUNDLE_IDENTIFIER\s*=\s*([^;]+);'),
          (match) => 'PRODUCT_BUNDLE_IDENTIFIER = $packageName;',
        );
        return newContent;
      } else {
        print("ensure package_name in pubspec.yaml");
        return source;
      }
    },
  );
}
